Change xs_read_watch interface to return a sized array (in userspace and in
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 7 Oct 2005 14:51:53 +0000 (15:51 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 7 Oct 2005 14:51:53 +0000 (15:51 +0100)
kernel).

Add index macros (XS_WATCH_*) for accessing the array to allow for future
expansion.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
tools/blktap/xenbus.c
tools/console/daemon/io.c
tools/python/xen/lowlevel/xs/xs.c
tools/xenstore/xenstored.h
tools/xenstore/xs.c
tools/xenstore/xs.h
tools/xenstore/xs_test.c

index 50919961f490a74a3bac0853dbff5db2f17c932f..763803297fcc4bd72dc1999a2f1c3a929c0dbf23 100644 (file)
@@ -200,14 +200,9 @@ static char *join(const char *dir, const char *name)
        return buffer;
 }
 
-char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
+static char **split(char *strings, unsigned int len, unsigned int *num)
 {
-       char *strings, *p, **ret;
-       unsigned int len;
-
-       strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
-       if (IS_ERR(strings))
-               return (char **)strings;
+       char *p, **ret;
 
        /* Count the strings. */
        *num = count_strings(strings, len);
@@ -224,8 +219,21 @@ char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
        strings = (char *)&ret[*num];
        for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
                ret[(*num)++] = p;
+
        return ret;
 }
+
+char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
+{
+       char *strings;
+       unsigned int len;
+
+       strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
+       if (IS_ERR(strings))
+               return (char **)strings;
+
+       return split(strings, len, num);
+}
 EXPORT_SYMBOL(xenbus_directory);
 
 /* Check if a path exists. Return 1 if it does. */
@@ -425,18 +433,19 @@ static int xs_watch(const char *path, const char *token)
        return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
 }
 
-static char *xs_read_watch(char **token)
+static char **xs_read_watch(unsigned int *num)
 {
        enum xsd_sockmsg_type type;
-       char *ret;
+       char *strings;
+       unsigned int len;
 
-       ret = read_reply(&type, NULL);
-       if (IS_ERR(ret))
-               return ret;
+       strings = read_reply(&type, &len);
+       if (IS_ERR(strings))
+               return (char **)strings;
 
        BUG_ON(type != XS_WATCH_EVENT);
-       *token = ret + strlen(ret) + 1;
-       return ret;
+
+       return split(strings, len, num);
 }
 
 static int xs_acknowledge_watch(const char *token)
@@ -519,8 +528,8 @@ void reregister_xenbus_watches(void)
 static int watch_thread(void *unused)
 {
        for (;;) {
-               char *token;
-               char *node = NULL;
+               char **vec = NULL;
+               unsigned int num;
 
                wait_event(xb_waitq, xs_input_avail());
 
@@ -530,23 +539,23 @@ static int watch_thread(void *unused)
                 */
                down(&xenbus_lock);
                if (xs_input_avail())
-                       node = xs_read_watch(&token);
+                       vec = xs_read_watch(&num);
 
-               if (node && !IS_ERR(node)) {
+               if (vec && !IS_ERR(vec)) {
                        struct xenbus_watch *w;
                        int err;
 
-                       err = xs_acknowledge_watch(token);
+                       err = xs_acknowledge_watch(vec[XS_WATCH_TOKEN]);
                        if (err)
                                printk(KERN_WARNING "XENBUS ack %s fail %i\n",
-                                      node, err);
-                       w = find_watch(token);
+                                      vec[XS_WATCH_TOKEN], err);
+                       w = find_watch(vec[XS_WATCH_TOKEN]);
                        BUG_ON(!w);
-                       w->callback(w, node);
-                       kfree(node);
-               } else if (node)
+                       w->callback(w, vec[XS_WATCH_PATH]);
+                       kfree(vec);
+               } else if (vec)
                        printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
-                              PTR_ERR(node));
+                              PTR_ERR(vec));
                up(&xenbus_lock);
        }
 }
index 48b085c2fb3d77769bb5adae1e09d92c75efc08a..c9cbea5fb34a505b243a0cf8db4a1f62adbf91ac 100644 (file)
@@ -251,13 +251,14 @@ int xs_fire_next_watch(struct xs_handle *h)
     char *node = NULL;
     struct xenbus_watch *w;
     int er;
+    unsigned int num;
 
-    res = xs_read_watch(h);
+    res = xs_read_watch(h, &num);
     if (res == NULL) 
         return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */
 
-    node  = res[0];
-    token = res[1];
+    node  = res[XS_WATCH_PATH];
+    token = res[XS_WATCH_TOKEN];
 
     er = xs_acknowledge_watch(h, token);
     if (er == 0)
index cde27b2dc78545f6a48654572e1c58697fed57a7..24afe0b5130c521c4ff5d9096f13a7ff64c827e9 100644 (file)
@@ -491,14 +491,15 @@ static void handle_xs(int fd)
        char **vec;
        int domid;
        struct domain *dom;
+       unsigned int num;
 
-       vec = xs_read_watch(xs);
+       vec = xs_read_watch(xs, &num);
        if (!vec)
                return;
 
-       if (!strcmp(vec[1], "domlist"))
+       if (!strcmp(vec[XS_WATCH_TOKEN], "domlist"))
                enum_domains();
-       else if (sscanf(vec[1], "dom%u", &domid) == 1) {
+       else if (sscanf(vec[XS_WATCH_TOKEN], "dom%u", &domid) == 1) {
                dom = lookup_domain(domid);
                if (dom->is_dead == false)
                        domain_create_ring(dom);
index 186455f6f6ce5fd1996755bcc01c73313a33997c..64a08e18923e794da7c1282edc57471de9ae14f1 100644 (file)
@@ -462,19 +462,20 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
     char **xsval = NULL;
     PyObject *token;
     int i;
+    unsigned int num;
 
     if (!xh)
         goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
         goto exit;
     Py_BEGIN_ALLOW_THREADS
-    xsval = xs_read_watch(xh);
+    xsval = xs_read_watch(xh, &num);
     Py_END_ALLOW_THREADS
     if (!xsval) {
         PyErr_SetFromErrno(PyExc_RuntimeError);
         goto exit;
     }
-    if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
+    if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)&token) != 1) {
         PyErr_SetString(PyExc_RuntimeError, "invalid token");
         goto exit;
     }
@@ -487,7 +488,7 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
         goto exit;
     }
     /* Create tuple (path, token). */
-    val = Py_BuildValue("(sO)", xsval[0], token);
+    val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
  exit:
     if (xsval)
         free(xsval);
index 3633e5eb74451521514f3c53b66b58a7df396cef..a84018d8e7414bd02dd99db94f97573f2cac280f 100644 (file)
@@ -86,4 +86,12 @@ struct xsd_sockmsg
        /* Generally followed by nul-terminated string(s). */
 };
 
+/* FIXME we shouldn't have to declare this in two places, what's the right
+   way to share things between xenstored.h and xs.h? */
+enum xs_watch_type
+{
+       XS_WATCH_PATH = 0,
+       XS_WATCH_TOKEN,
+};
+
 #endif /* _XENSTORED_H */
index a842a6e39c6838325f0ce8d55714313baa5c7209..4f21bbc5908eedbda18935e7da926a0f723883e3 100644 (file)
@@ -449,25 +449,44 @@ bool xs_watch(struct xs_handle *h, const char *path, const char *token)
  * Returns array of two pointers: path and token, or NULL.
  * Call free() after use.
  */
-char **xs_read_watch(struct xs_handle *h)
+char **xs_read_watch(struct xs_handle *h, unsigned int *num)
 {
        struct xsd_sockmsg msg;
        char **ret;
+       char *strings;
+       unsigned int num_strings, i;
 
        if (!read_all(h->fd, &msg, sizeof(msg)))
                return NULL;
 
        assert(msg.type == XS_WATCH_EVENT);
-       ret = malloc(sizeof(char *)*2 + msg.len);
-       if (!ret)
+       strings = malloc(msg.len);
+       if (!strings)
                return NULL;
 
-       ret[0] = (char *)(ret + 2);
-       if (!read_all(h->fd, ret[0], msg.len)) {
-               free_no_errno(ret);
+       if (!read_all(h->fd, strings, msg.len)) {
+               free_no_errno(strings);
                return NULL;
        }
-       ret[1] = ret[0] + strlen(ret[0]) + 1;
+
+       num_strings = xs_count_strings(strings, msg.len);
+
+       ret = malloc(sizeof(char*) * num_strings + msg.len);
+       if (!ret) {
+               free_no_errno(strings);
+               return NULL;
+       }
+
+       ret[0] = (char *)(ret + num_strings);
+       memcpy(ret[0], strings, msg.len);
+       free(strings);
+
+       for (i = 1; i < num_strings; i++) {
+               ret[i] = ret[i - 1] + strlen(ret[i - 1]) + 1;
+       }
+
+       *num = num_strings;
+
        return ret;
 }
 
index bd4bcbd348bff39b01faf9a05071e948e4b069c4..351f55a4101bab4925217d8020ac0620019109aa 100644 (file)
 
 struct xs_handle;
 
+/* FIXME we shouldn't have to declare this in two places, what's the right
+   way to share things between xenstored.h and xs.h? */
+enum xs_watch_type
+{
+       XS_WATCH_PATH = 0,
+       XS_WATCH_TOKEN,
+};
+
 /* On failure, these routines set errno. */
 
 /* Connect to the xs daemon.
@@ -91,10 +99,10 @@ bool xs_watch(struct xs_handle *h, const char *path, const char *token);
 int xs_fileno(struct xs_handle *h);
 
 /* Find out what node change was on (will block if nothing pending).
- * Returns array of two pointers: path and token, or NULL.
- * Call free() after use.
+ * Returns array containing the path and token. Use XS_WATCH_* to access these
+ * elements. Call free() after use.
  */
-char **xs_read_watch(struct xs_handle *h);
+char **xs_read_watch(struct xs_handle *h, unsigned int *num);
 
 /* Acknowledge watch on node.  Watches must be acknowledged before
  * any other watches can be read.
index e55057f572693da17e767f00edfdf0b64413d6a3..00c7ba7beac8b2e456530a4e574c4ca750816890 100644 (file)
@@ -489,8 +489,11 @@ static void do_watch(unsigned int handle, const char *node, const char *token,
 
        /* Convenient for testing... */
        if (swallow_event) {
-               char **vec = xs_read_watch(handles[handle]);
-               if (!vec || !streq(vec[0], node) || !streq(vec[1], token))
+               unsigned int num;
+               char **vec = xs_read_watch(handles[handle], &num);
+               if (!vec ||
+                   !streq(vec[XS_WATCH_PATH], node) ||
+                   !streq(vec[XS_WATCH_TOKEN], token))
                        failed(handle);
                if (!xs_acknowledge_watch(handles[handle], token))
                        failed(handle);
@@ -522,6 +525,7 @@ static void do_waitwatch(unsigned int handle)
        struct timeval tv = {.tv_sec = timeout_ms/1000,
                             .tv_usec = (timeout_ms*1000)%1000000 };
        fd_set set;
+       unsigned int num;
 
        if (xs_fileno(handles[handle]) != -2) {
                /* Manually select here so we can time out gracefully. */
@@ -537,16 +541,17 @@ static void do_waitwatch(unsigned int handle)
                set_timeout();
        }
 
-       vec = xs_read_watch(handles[handle]);
+       vec = xs_read_watch(handles[handle], &num);
        if (!vec) {
                failed(handle);
                return;
        }
 
        if (handle)
-               output("%i:%s:%s\n", handle, vec[0], vec[1]);
+               output("%i:%s:%s\n", handle,
+                      vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
        else
-               output("%s:%s\n", vec[0], vec[1]);
+               output("%s:%s\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
        free(vec);
 }